home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 401-425 / disk_405 / gifmachine / sources / writeiff.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  9KB  |  424 lines

  1. /* Copyright 1990 by Christopher A. Wichura.
  2.    See file GIFMachine.doc for full description of rights.
  3. */
  4.  
  5. #include "GIFMachine.h"
  6. #include <iff/ILBM.h>
  7. #include <libraries/iffparse.h>
  8. #include <graphics/view.h>
  9. #include <proto/iffparse.h>
  10. #include <dos/datetime.h>
  11.  
  12. extern struct GIFdescriptor gdesc;
  13. EXTERNBITPLANE;
  14.  
  15. extern struct MinList CommentList;
  16.  
  17. extern char *AbortMsg;
  18.  
  19. extern UWORD *SHAMmem;
  20. BYTE *PlaneBuf;
  21.  
  22. BOOL Laced;
  23.  
  24. UBYTE *Planes[8];
  25.  
  26. static UBYTE CompBuf[256];
  27. static ULONG PlanePos;
  28.  
  29. /* our version number stuff */
  30. extern ULONG __far Version;
  31. extern ULONG __far Revision;
  32.  
  33. BOOL WriteIFF(char *tofile, BOOL DeepFlag)
  34. {
  35.     register struct IFFHandle *iff;
  36.     register int index;
  37.     register ULONG ChunkSize;
  38.     register UWORD current;
  39.     char WrittenBy[40];
  40.  
  41.     ColorRegister ColourBuf;
  42.  
  43.     PutStr("...Writing IFF file.");
  44.  
  45.     if (!(iff = AllocIFF())) {
  46.         PutStr("\n......Error allocating IFF handle.\n");
  47.         return TRUE;
  48.     }
  49.  
  50.     if (!(iff->iff_Stream = Open(tofile, MODE_NEWFILE))) {
  51.         MyPrintf("\n......Error %ld trying to create %s.", IoErr(), tofile);
  52.         goto EndWriteIFF;
  53.     }
  54.  
  55.     InitIFFasDOS(iff);
  56.  
  57.     if (OpenIFF(iff, IFFF_WRITE)) {
  58.         PutStr("\n......Error writing to IFF.\n");
  59.         goto EndWriteIFF;
  60.     }
  61.  
  62.     if (PushChunk(iff, ID_ILBM, FORM, IFFSIZE_UNKNOWN)) {
  63.         PutStr("\n......Error writing to IFF.\n");
  64.         goto EndWriteIFF;
  65.     }
  66.  
  67.     if (PushChunk(iff, 0L, MakeID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
  68.         PutStr("\n......Error writing to IFF.\n");
  69.         goto EndWriteIFF;
  70.     }
  71.  
  72.     MySPrintf(WrittenBy, "Written by GIFMachine v%ld.%ld on ", Version, Revision);
  73.  
  74.     if (WriteChunkBytes(iff, (APTR)&WrittenBy, strlen(WrittenBy)) != strlen(WrittenBy)) {
  75.         PutStr("\n......Error writing to IFF.\n");
  76.         goto EndWriteIFF;
  77.     }
  78.  
  79.     {
  80.         struct DateTime dat;
  81.         char Date[LEN_DATSTRING + 1];
  82.         int DateLength;
  83.  
  84.         DateStamp((LONG *)&dat.dat_Stamp);
  85.         dat.dat_Format = FORMAT_DOS;
  86.         dat.dat_Flags = 0;
  87.         dat.dat_StrDay = NULL;
  88.         dat.dat_StrDate = Date;
  89.         dat.dat_StrTime = NULL;
  90.  
  91.         memset(Date, 0, LEN_DATSTRING + 1);
  92.         DateToStr(&dat);
  93.  
  94.         DateLength = strlen(Date) + 1;
  95.         if (WriteChunkBytes(iff, (APTR)&Date, DateLength) != DateLength) {
  96.             PutStr("\n......Error writing to IFF.\n");
  97.             goto EndWriteIFF;
  98.         }
  99.     }
  100.  
  101.     if (PopChunk(iff)) {
  102.         PutStr("\n......Error writing to IFF.\n");
  103.         goto EndWriteIFF;
  104.     }
  105.  
  106.     {
  107.         struct CommentNode *cn;
  108.         char ANNObuf[1];
  109.  
  110. #define C_BLOCK_ID "GIF Comment Block: "
  111.  
  112.         ANNObuf[0] = 0;
  113.  
  114.         while (cn = (struct CommentNode *)RemHead((struct List *)&CommentList)) {
  115.             if (PushChunk(iff, 0L, MakeID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
  116.                 PutStr("\n......Error writing to IFF.\n");
  117.                 goto EndWriteIFF;
  118.             }
  119.  
  120.             if (WriteChunkBytes(iff, (APTR)C_BLOCK_ID, strlen(C_BLOCK_ID)) != strlen(C_BLOCK_ID)) {
  121.                 PutStr("\n......Error writing to IFF.\n");
  122.                 goto EndWriteIFF;
  123.             }
  124.  
  125.             if (WriteChunkBytes(iff, (APTR)cn->cn_Comment, cn->cn_CommentLength) != cn->cn_CommentLength) {
  126.                 PutStr("\n......Error writing to IFF.\n");
  127.                 goto EndWriteIFF;
  128.             }
  129.  
  130.             if (WriteChunkBytes(iff, (APTR)ANNObuf, 1) != 1) {
  131.                 PutStr("\n......Error writing to IFF.\n");
  132.                 goto EndWriteIFF;
  133.             }
  134.  
  135.             if (PopChunk(iff)) {
  136.                 PutStr("\n......Error writing to IFF.\n");
  137.                 goto EndWriteIFF;
  138.             }
  139.         }
  140.     }
  141.  
  142.     if (PushChunk(iff, 0L, ID_BMHD, sizeof(BitMapHeader))) {
  143.         PutStr("\n......Error writing to IFF.\n");
  144.         goto EndWriteIFF;
  145.     }
  146.  
  147.     {
  148.         BitMapHeader    bmh;
  149.  
  150.         bmh.w                 = gdesc.gd_Width & ~1L; /* make sure width is even */
  151.         bmh.h                 = gdesc.gd_Height;
  152.         bmh.x       = bmh.y  = 0;
  153.         bmh.nPlanes          = (DeepFlag ? 24 : 6);
  154.         bmh.masking          = mskNone;
  155.         bmh.compression      = cmpByteRun1;
  156.         bmh.pad1             = 0;
  157.         bmh.transparentColor = 0;
  158.         bmh.xAspect          = (Laced ? x320x400Aspect : x320x200Aspect);
  159.         bmh.yAspect          = (Laced ? y320x400Aspect : y320x200Aspect);
  160.         bmh.pageWidth        = 320;
  161.         bmh.pageHeight       = (Laced ? 400 : 200);
  162.  
  163.         if (WriteChunkBytes(iff, (APTR)&bmh, sizeof(BitMapHeader)) != sizeof(BitMapHeader)) {
  164.             PutStr("\n......Error writing to IFF.\n");
  165.             goto EndWriteIFF;
  166.         }
  167.     }
  168.  
  169.     if (PopChunk(iff)) {
  170.         PutStr("\n......Error writing to IFF.\n");
  171.         goto EndWriteIFF;
  172.     }
  173.  
  174.     if (PushChunk(iff, 0L, ID_CAMG, 4)) {
  175.         PutStr("\n......Error writing to IFF.\n");
  176.         goto EndWriteIFF;
  177.     }
  178.  
  179.     {
  180.         LONG CAMGbuf[1];
  181.  
  182.         CAMGbuf[0] = (DeepFlag ? 0 : HAM) | (Laced ? LACE : 0);
  183.  
  184.         if (WriteChunkBytes(iff, (APTR)&CAMGbuf, 4) != 4) {
  185.             PutStr("\n......Error writing to IFF.\n");
  186.             goto EndWriteIFF;
  187.         }
  188.     }
  189.  
  190.     if (PopChunk(iff)) {
  191.         PutStr("\n......Error writing to IFF.\n");
  192.         goto EndWriteIFF;
  193.     }
  194.  
  195.     if (!DeepFlag) {
  196.         if (PushChunk(iff, 0L, ID_CMAP, 16 * 3)) {
  197.             PutStr("\n......Error writing to IFF.\n");
  198.             goto EndWriteIFF;
  199.         }
  200.  
  201.         for (index = 0; index < 16; index++) {
  202.             current = SHAMmem[index];
  203.  
  204.             ColourBuf.red   = (current >> 4) & 0xF0;
  205.             ColourBuf.green = current & 0xF0;
  206.             ColourBuf.blue  = (current & 15) << 4;
  207.  
  208.             if (WriteChunkBytes(iff, (APTR)&ColourBuf, sizeofColorRegister) != sizeofColorRegister) {
  209.                 PutStr("\n......Error writing to IFF.\n");
  210.                 goto EndWriteIFF;
  211.             }
  212.         }
  213.  
  214.         if (PopChunk(iff)) {
  215.             PutStr("\n......Error writing to IFF.\n");
  216.             goto EndWriteIFF;
  217.         }
  218.  
  219.         ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
  220.  
  221.         if (PushChunk(iff, 0L, MakeID('S','H','A','M'), ChunkSize + 2)) {
  222.             PutStr("\n......Error writing to IFF.\n");
  223.             goto EndWriteIFF;
  224.         }
  225.  
  226.         {
  227.             UWORD SHAMversion[1];
  228.  
  229.             SHAMversion[0] = 0;
  230.  
  231.             if (WriteChunkBytes(iff, (APTR)&SHAMversion, sizeof(UWORD)) != sizeof(UWORD)) {
  232.                 PutStr("\n......Error writing to IFF.\n");
  233.                 goto EndWriteIFF;
  234.             }
  235.         }
  236.  
  237.         if (WriteChunkBytes(iff, (APTR)SHAMmem, ChunkSize) != ChunkSize) {
  238.             PutStr("\n......Error writing to IFF.\n");
  239.             goto EndWriteIFF;
  240.         }
  241.  
  242.         if (PopChunk(iff)) {
  243.             PutStr("\n......Error writing to IFF.\n");
  244.             goto EndWriteIFF;
  245.         }
  246.     } /* end if (!DeepFlag) */
  247.  
  248.     if (PushChunk(iff, 0L, ID_BODY, IFFSIZE_UNKNOWN)) {
  249.         PutStr("\n......Error writing to IFF.\n");
  250.         goto EndWriteIFF;
  251.     }
  252.  
  253.     /* now we actually write the body chunk out */
  254.     {
  255.         register int plane;
  256.         register int col;
  257.         register UWORD x;
  258.         register UWORD y;
  259.         register int index;
  260.         UBYTE PlaneMask, ColMask;
  261.         UWORD Cols;
  262.  
  263.         PutStr("\n......Line ");
  264.  
  265.         Cols = (gdesc.gd_Width + 7) / 8;
  266.         if (IS_ODD(Cols))
  267.             Cols++;
  268.  
  269.         for (y = 0; y < gdesc.gd_Height; y++) {
  270.             MyPrintf("%5ld", y);
  271.  
  272.             if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
  273.                 MyPrintf("\n%s", AbortMsg);
  274.                 CloseIFF(iff);
  275.                 Close(iff->iff_Stream);
  276.                 FreeIFF(iff);
  277.                 MyExit(ABORTEXITVAL);
  278.             }
  279.  
  280.             for (index = 0; index < (DeepFlag ? 3 : 1); index++) {
  281.                 col = 0;
  282.                 ColMask = 1L << 7;
  283.  
  284.                 for (x = 0; x < gdesc.gd_Width; x++) {
  285.                     if (DeepFlag)
  286.                         current = *((UBYTE *)&BitPlane[y][x]+index);
  287.                     else
  288.                         current = GetValue(x, y);
  289.  
  290.                     PlaneMask = 1;
  291.                     for (plane = 0; plane < (DeepFlag ? 8 : 6); plane++) {
  292.                         if (current & PlaneMask)
  293.                             Planes[plane][col] |= ColMask;
  294.  
  295.                         PlaneMask <<= 1;
  296.                     }
  297.  
  298.                     if (ColMask == 1) {
  299.                         ColMask = 1L << 7;
  300.                         col++;
  301.                     } else
  302.                         ColMask >>= 1;
  303.                 }
  304.  
  305.                 /* now we need to compress the scan line */
  306.  
  307.                 {
  308.                     register BOOL state;
  309.                     register char c;
  310.                     register char lastc;
  311.                     register UWORD nbuf;
  312.                     register UWORD rstart;
  313.  
  314.                     for (plane = 0; plane < (DeepFlag ? 8 : 6); plane++) {
  315.  
  316.                         CompBuf[0] = lastc = c = Planes[plane][0];
  317.  
  318.                         state = FALSE;
  319.                         PlanePos = rstart = 0;
  320.                         nbuf = col = 1;
  321.  
  322.                         while (col < Cols) {
  323.                             CompBuf[nbuf++] = c = Planes[plane][col++];
  324.  
  325.                             switch (state) {
  326.                                 case FALSE:
  327.                                 if (nbuf > 128) {
  328.                                     OutDump(nbuf - 1);
  329.                                     CompBuf[0] = c;
  330.                                     nbuf = 1;
  331.                                     rstart = 0;
  332.                                     break;
  333.                                 }
  334.  
  335.                                 if (c == lastc) {
  336.                                     if (nbuf - rstart >= 3) {
  337.                                         if (rstart > 0)
  338.                                             OutDump(rstart);
  339.                                         state = TRUE;
  340.                                     } else if (rstart == 0)
  341.                                         state = TRUE;
  342.                                 } else
  343.                                     rstart = nbuf - 1;
  344.  
  345.                                 break;
  346.  
  347.                                 case TRUE:
  348.                                 if ((c != lastc) || (nbuf - rstart > 128)) {
  349.                                     OutRun(nbuf - 1 - rstart, lastc);
  350.                                     CompBuf[0] = c;
  351.                                     nbuf = 1;
  352.                                     rstart = 0;
  353.                                     state = FALSE;
  354.                                 }
  355.  
  356.                                 break;
  357.                             }
  358.  
  359.                             lastc = c;
  360.                         }
  361.  
  362.                         switch (state) {
  363.                             case FALSE:
  364.                             OutDump(nbuf);
  365.                             break;
  366.  
  367.                             case TRUE:
  368.                             OutRun(nbuf - rstart, lastc);
  369.                             break;
  370.                         }
  371.  
  372.                         /* now write the compressed plane out */
  373.                         if (WriteChunkBytes(iff, (APTR)PlaneBuf, PlanePos) != PlanePos) {
  374.                             PutStr("\n......Error writing to IFF.\n");
  375.                             goto EndWriteIFF;
  376.                         }
  377.  
  378.                         memset((char *)Planes[plane], 0, Cols);
  379.                     }
  380.                 }
  381.             }
  382.  
  383.             MyPrintf("\x9B" "5D");
  384.         }
  385.  
  386.     }
  387.  
  388.     if (PopChunk(iff)) {
  389.         PutStr("\n......Error writing to IFF.\n");
  390.         goto EndWriteIFF;
  391.     }
  392.  
  393.     if (PopChunk(iff)) {
  394.         PutStr("\n......Error writing to IFF.\n");
  395.         goto EndWriteIFF;
  396.     }
  397.  
  398.     PutStr("\x9B" "5D\x9BKWritten.\n");
  399.  
  400. EndWriteIFF:
  401.     CloseIFF(iff);
  402.     if (iff->iff_Stream)
  403.         Close(iff->iff_Stream);
  404.     FreeIFF(iff);
  405.  
  406.     return TRUE;
  407. }
  408.  
  409. void OutDump(int nn)
  410. {
  411.     register int index;
  412.  
  413.     PlaneBuf[PlanePos++] = nn - 1;
  414.  
  415.     for (index = 0; index < nn; index++)
  416.         PlaneBuf[PlanePos++] = CompBuf[index];
  417. }
  418.  
  419. void OutRun(int nn, int cc)
  420. {
  421.     PlaneBuf[PlanePos++] = -(nn - 1);
  422.     PlaneBuf[PlanePos++] = cc;
  423. }
  424.